/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ajustecurvas.controller;

import ajustecurvas.Ponto;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author positivo
 */
public class ExponencialAjusteController extends AjusteController {

    String equacaoStting;
    double r = 0;

    @Override
    public List<Ponto> calcular(List<Ponto> medidas) {

        double[] xi = separarEixo(medidas, 0);
        double[] yi = separarEixo(medidas, 1);
        double[] y;
        int n = 11;

        double[] Yi = calcularYi(yi); //ln(yi)
        double[] xiYi = calcularXiYi(xi, Yi);
        double[] xi2 = calcularQuadrado(xi);
        double[] Yi2 = calcularQuadrado(Yi);

        double soma_xi = soma(xi);
        double soma_yi = soma(yi);
        double soma_xiYi = soma(xiYi);
        double soma_Yi = soma(Yi);
        double soma_xi2 = soma(xi2);
        double soma_Yi2 = soma(Yi2);

//        System.out.println("Soma xi: " + soma_xi);
//        System.out.println("Soma yi: " + soma_yi);
//        System.out.println("Soma Yi: " + soma_Yi);
//        System.out.println("Soma xiYi: " + soma_xiYi);
//        System.out.println("Soma xi2: " + soma_xi2);
//        System.out.println("Soma Yi2: " + soma_Yi2);

        double aln = calculaA(n, soma_xiYi, soma_xi, soma_Yi, soma_xi2);
        double bln = calculaB(soma_Yi, aln, soma_xi, n);

        double a = Math.exp(aln);
        double b = Math.exp(bln);
//
//        System.out.println("A: " + a);
//        System.out.println("B: " + b);

        y = calcularY(a, b, xi);
        gerarEquacao(a, b);


        gerarPontos(xi, y, medidas);
        r = gerarQualidade(soma_xiYi, soma_xi, soma_Yi, n, soma_xi2, soma_Yi2);

//        for (int i = 0; i < medidas.size(); i++) {
//            System.out.println("x: " +medidas.get(i).getX() +" y: " +medidas.get(i).getY());
//        }

        return gerarPontos(xi, y, medidas);

    }

    @Override
    public String getEquacao() {
        return equacaoStting;
    }

    @Override
    public double getQualidade() {
        return r;
    }

    private double[] separarEixo(List<Ponto> medidas, int j) {
        double[] valores = new double[medidas.size()];

        for (int i = 0; i < valores.length; i++) {
            if (j == 0) {
                valores[i] = medidas.get(i).getX();
            } else {
                valores[i] = medidas.get(i).getY();
            }
        }

        return valores;
    }

    private double soma(double[] vetor) {
        double total = 0;

        for (int i = 0; i < vetor.length; i++) {
            total = total + vetor[i];
        }

        return total;
    }

    private double[] calcularYi(double[] yi) {

        double[] Yi = new double[yi.length];

        for (int i = 0; i < yi.length; i++) {
            Yi[i] = Math.log(yi[i]);
        }

        return Yi;
    }

    private double[] calcularXiYi(double[] xi, double[] Yi) {
        double[] xiYi = new double[xi.length];

        for (int i = 0; i < xi.length; i++) {
            xiYi[i] = xi[i] * Yi[i];
        }

        return xiYi;
    }

    private double[] calcularQuadrado(double[] v) {
        double[] v2 = new double[v.length];

        for (int i = 0; i < v.length; i++) {
            v2[i] = Math.pow(v[i], 2);
        }

        return v2;
    }

    private double calculaA(int n, double soma_xiYi, double soma_xi, double soma_Yi, double soma_xi2) {
        double de = (n * soma_xiYi) - (soma_xi * soma_Yi);
        double di = (n * soma_xi2) - (Math.pow(soma_xi, 2));
        return (de / di);

    }

    private double calculaB(double soma_Yi, double a, double soma_xi, int n) {
        double de = soma_Yi - (a * soma_xi);
        double di = n;
        return de / di;
    }

    private double[] calcularY(double a, double b, double[] xi) {
        double v[] = new double[xi.length];

        for (int i = 0; i < xi.length; i++) {
            v[i] = b * (Math.pow(a, xi[i]));
        }

        return v;
    }

    private List<Ponto> gerarPontos(double[] xi, double[] y, List<Ponto> pontos) {

        
        ArrayList<Ponto> lista = new ArrayList<Ponto>();

        for (int i = 0; i < xi.length; i++) {
            Ponto p = new Ponto(xi[i], y[i]);
            lista.add(p);
        }

        return lista;
    }

    private String gerarEquacao(double a, double b) {
        DecimalFormat df = new DecimalFormat("0.00");
        String A = df.format(a);
        String B = df.format(b);
        equacaoStting = B + " * " + A + "^x";

        return equacaoStting;
    }

    private double gerarQualidade(double soma_xiYi, double soma_xi, double soma_Yi, int n, double soma_xi2, double soma_Yi2) {
        double de = Math.pow(soma_xiYi - (soma_xi * soma_Yi) / n, 2);
        double di1 = soma_xi2 - (Math.pow(soma_xi, 2) / n);
        double di2 = (soma_Yi2 - (Math.pow(soma_Yi, 2) / n));

        return de/(di1*di2);
    }
}
